#include "SerialPort.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "soc/uart_periph.h"

#define TAG "SerialPort"

SerialPort::SerialPort(uart_port_t port, uart_config_t config, int tx_io_num, int rx_io_num)
{
    m_buf = (unsigned char*)malloc(REC_BUF_MAX);
    if (uart_is_driver_installed(port)) {
		ESP_LOGE(TAG, "UART_NUM_%d already been uesd!",port);
		uart_driver_delete(port);
		// 取消外设1的uart引脚映射
		//esp_rom_gpio_connect_out_signal(UART_TXD_1, uart_periph_signal[port].tx_sig, 0, 1);
	}

    uart_driver_install(port, REC_BUF_MAX * 2, 0, 0, NULL, 0);
    uart_param_config(port, &config);
    uart_set_pin(port, tx_io_num, rx_io_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    m_port = port;
    ESP_LOGI(TAG,"UART_NUM_%d UART_NUM_MAX=%d install success",m_port,UART_NUM_MAX);
    m_buf_len = 0;
}

SerialPort::~SerialPort()
{
    free(m_buf);
}

void SerialPort::appendRecBuf(unsigned char *buf, int len)
{
    if (len <= 0)
        return;
    if (len > REC_BUF_MAX)
    {
        memcpy(m_buf, buf + len - REC_BUF_MAX, REC_BUF_MAX);
        m_buf_len = REC_BUF_MAX;
        return;
    }
    else if (len + m_buf_len > REC_BUF_MAX)
    {
        decRecBuf(len + m_buf_len - REC_BUF_MAX);
    }
    memcpy(m_buf + m_buf_len, buf, len);
    m_buf_len += len;
}

void SerialPort::decRecBuf(int len)
{
    if (len <= 0)
        return;
    if (len >= REC_BUF_MAX || len >= m_buf_len)
    {
        m_buf_len = 0;
    }
    else
    {
        memcpy(m_buf, m_buf + len, m_buf_len - len);
        m_buf_len -= len;
    }
}

int SerialPort::read()
{
    int n = 0;
    size_t nLen;
    uart_get_buffered_data_len(m_port, &nLen);
    {
        if (nLen > 0)
        {
            unsigned char buf[255];
            n = uart_read_bytes(m_port, buf, 255, 100/ portTICK_PERIOD_MS);
            appendRecBuf(buf, n);
        }
    }
    return n;
}

void SerialPort::write(unsigned char *buf, int len)
{
    uart_write_bytes(m_port, buf, len);
}
